package com.xiaobo.sql.component.condition;

import com.xiaobo.sql.base.Column;
import com.xiaobo.sql.base.Condition;
import com.xiaobo.sql.enmus.ConditionLogicType;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * 查询条件抽象类
 * @author duxiaobo
 * @date 2021/11/24 22:46
 */
public abstract class AbstractCondition implements Condition {
    protected Column column;
    private List<ConditionLi> conditionLis;

    public AbstractCondition() {
    }

    public AbstractCondition(Column column) {
        this.column = column;
    }

    public AbstractCondition and(AbstractCondition abstractCondition) {
        if (Objects.isNull(abstractCondition)) {
            return this;
        }
        if (Objects.isNull(this.conditionLis)) {
            conditionLis = new LinkedList<>();
        }
        conditionLis.add(new ConditionLi(ConditionLogicType.and, abstractCondition));
        return this;
    }

    public AbstractCondition or(AbstractCondition abstractCondition) {
        if (Objects.isNull(abstractCondition)) {
            return this;
        }
        if (Objects.isNull(this.conditionLis)) {
            conditionLis = new LinkedList<>();
        }
        conditionLis.add(new ConditionLi(ConditionLogicType.or, abstractCondition));
        return this;
    }

    protected abstract void subSQL(StringBuilder sql);

    @Override
    public final void toSql(StringBuilder sql) {
        subSQL(sql);
        if (isMulti()) {
            conditionLis.forEach(li -> {
                sql.append(li.logicType.getSymbol());
                AbstractCondition condition = li.abstractCondition;
                if (condition.isMulti()) {
                    sql.append("(");
                    condition.toSql(sql);
                    sql.append(")");
                } else {
                    condition.toSql(sql);
                }
            });
        }
    }

    public class ConditionLi {
        ConditionLogicType logicType;
        AbstractCondition abstractCondition;

        public ConditionLi(ConditionLogicType logicType, AbstractCondition abstractCondition) {
            this.logicType = logicType;
            this.abstractCondition = abstractCondition;
        }
    }

    protected boolean isMulti() {
        return conditionLis != null && !conditionLis.isEmpty();
    }

}
